<template>
    <div style="position: relative;">
        <!-- 用div来模拟条 -->
        <div class="calendar_bar" @click.stop="showMenu = true">
            <span v-show="value">
                {{ xhY }} - {{ xhM }} - {{ xhD }}
            </span>
        </div>

        <!-- 绝对定位的盒子中 -->
        <div class="calendar_menu" v-show="showMenu" @click.stop>
            <!-- 头部，切换年月的 -->
            <div class="calendar_header">
                <div class="left">
                    <span :class="{ disabeld: year == startYear }" @click="yearMinus">&lt;&lt;</span>
                    <span :class="{ disabeld: year == startYear && month == 1 }" @click="monthMinus">&lt;</span>
                </div>
                <div class="center">
                    <select v-model.number="year">
                        <option v-for="i in endYear - startYear + 1" :key="i">
                            {{ startYear + i - 1 }}
                        </option>
                    </select>
                    年

                    <span style="display: inline-block; width: 10px;"></span>

                    <select v-model.number="month">
                        <option v-for="i in 12" :key="i">
                            {{ i }}
                        </option>
                    </select>
                    月
                </div>
                <div class="right">
                    <span :class="{ disabeld: year == endYear && month == 12 }" @click="monthAdd">&gt;</span>
                    <span :class="{ disabeld: year == endYear }" @click="yearAdd">&gt;&gt;</span>
                </div>
            </div>

            <!-- 表格 -->
            <div class="table_box">
                <table>
                    <tr>
                        <th>日</th>
                        <th>一</th>
                        <th>二</th>
                        <th>三</th>
                        <th>四</th>
                        <th>五</th>
                        <th>六</th>
                    </tr>
                    <tr v-for="i in 6" :key="i">
                        <td v-for="j in 7" :key="j" :class="{ dan: getO(i, j).m != month }"
                            @click="xuanhaole(getO(i, j))">
                            <p>
                                {{ getO(i, j).d }}
                            </p>
                            <p>
                                {{ nongli(getO(i, j)) }}
                            </p>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
</template>
  
<script>
import solarLunar from 'solarlunar';

export default {
    props: ['value'],
    created() {
        // 给文档添加监听，不能监听onclick，因为会覆盖。addEventListener不覆盖。必须监听冒泡阶段。
        document.addEventListener('click', () => {
            this.showMenu = false;
        }, false);
    },
    data() {
        // 今天
        let d = new Date();
        let dd = new Date(this.value);

        return {
            // 当前已经选好了的年月日,如果双向绑定传进来一个值，那么用双向绑定的这个年月日
            xhY: this.value ? dd.getFullYear() : '',
            xhM: this.value ? dd.getMonth() + 1 : '',
            xhD: this.value ? dd.getDate() : '',
            // 是否显示菜单
            showMenu: false,
            // 开始年份、结束年份
            startYear: 2003,
            endYear: 2022,
            // 当前年，没有传，就今天的年
            year: Number(this.y) || d.getFullYear(),
            // 当前月，这里是人类真实的月份，不需要减1
            month: Number(this.m) || d.getMonth() + 1,
            jiejiari: [
                { y: 2022, m: 10, d: 1, title: '国庆节' },
                { y: 2022, m: 10, d: 2, title: '国庆节' },
                { y: 2022, m: 10, d: 3, title: '国庆节' },
                { y: 2022, m: 10, d: 4, title: '国庆节' },
                { y: 2022, m: 10, d: 5, title: '国庆节' },
                { y: 2022, m: 10, d: 6, title: '国庆节' },
                { y: 2022, m: 10, d: 7, title: '国庆节' }
            ]
        }
    },
    computed: {
        // 这个月1号星期几
        zhegeyue1haoxingqiji() {
            return (new Date(this.year, this.month - 1, 1)).getDay();
        },
        // 上个月有几天，就是本月0号的日子
        shanggeyueyoujitian() {
            return (new Date(this.year, this.month - 1, 0)).getDate();
        },
        // 本月有几天，就是下个月0号的日子
        benyueyoujitian() {
            return (new Date(this.year, this.month, 0)).getDate();
        },
        // 大数组
        // [30,31,1,2,3,4,5,6,7,8,9,10,11,12,……,29,30,1,2,3,4,5,6,7,8,9,10]
        // [{y: ,m:,r:},{y: ,m:,r:},{y: ,m:,r:},{y: ,m:,r:},{y: ,m:,r:}]
        dashuzu() {
            let arr = [];
            // 本月1号星期几，数组中，就推入几项上个月的尾巴。
            // 如果是星期日，推入7个。
            let nn = this.zhegeyue1haoxingqiji == 0 ? 7 : this.zhegeyue1haoxingqiji;
            for (let i = 0; i < nn; i++) {
                arr.unshift({
                    y: this.month == 1 ? this.year - 1 : this.year,
                    m: this.month == 1 ? 12 : this.month - 1,
                    d: this.shanggeyueyoujitian - i
                });
            }

            // 推入本月的
            for (let i = 1; i <= this.benyueyoujitian; i++) {
                arr.push({
                    y: this.year,
                    m: this.month,
                    d: i
                });
            }

            // 推入下个月的
            let count = 1;
            // 直到凑齐42项
            while (arr.length < 42) {
                arr.push({
                    y: this.month == 12 ? this.year + 1 : this.year,
                    m: this.month == 12 ? 1 : this.month + 1,
                    d: count
                });
                count++;
            }

            return arr;
        }
    },
    methods: {
        // 显示农历
        nongli(o) {
            // 这一天的信息
            let info = solarLunar.solar2lunar(o.y, o.m, o.d);

            if (info.term) {
                return info.term;
            } else {
                if (info.dayCn == '初一') {
                    // 初一就显示汉字月份，比如“十月”
                    return info.monthCn;
                } else {
                    return info.dayCn;
                }
            }
        },
        // 月份减
        monthMinus() {
            if (this.month == 1) {
                if (this.year > this.startYear) {
                    this.year--;
                    this.month = 12;
                }
            } else {
                this.month--;
            }
        },
        // 月份加
        monthAdd() {
            if (this.month == 12) {
                if (this.year < this.endYear) {
                    this.year++;
                    this.month = 1;
                }
            } else {
                this.month++;
            }
        },
        // 年份减
        yearMinus() {
            if (this.year > this.startYear) {
                this.year--;
            }
        },
        // 年份加
        yearAdd() {
            if (this.year < this.endYear) {
                this.year++;
            }
        },
        // 从大数组中得到i、j这行列的对象
        getO(i, j) {
            return this.dashuzu[(i - 1) * 7 + j - 1];
        },
        // 选好了
        xuanhaole(o) {
            let { y, m, d } = o;
            let ts = (new Date(y, m - 1, d)).getTime();

            // 告诉父亲
            this.$emit('input', ts);

            // 关闭菜单
            this.showMenu = false;

            // 选好
            this.xhY = y;
            this.xhM = m;
            this.xhD = d;
        }
    },
    watch: {
        // 监控props变化，value是v-model的值，一旦变化，重新算data的xhY、xhM、xhD
        value(newValue) {
            let dd = new Date(newValue);
            // 改变data
            this.xhY = dd.getFullYear();
            this.xhM = dd.getMonth() + 1;
            this.xhD = dd.getDate();
        }
    }
}
</script>
  
<style lang="less">
// 条
.calendar_bar {
    width: 212px;
    height: 33px;
    border: 1px solid #dcdfe6;
    border-radius: 5px;
    cursor: pointer;
    line-height: 33px;
    padding-left: 10px;
    color: #606266;
}

.calendar_menu {
    padding: 10px;
    position: absolute;
    z-index: 999;
    left: 0;
    top: 40px;
    background-color: white;
    border-radius: 6px;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);

    .calendar_header {
        width: 360px;
        display: flex;
    }

    .calendar_header span {
        font-size: 14px;
        font-family: consolas;
        // 小手图标
        cursor: pointer;
        // 不能被选中
        user-select: none;

        // 在less中&符号表示它自己
        &:hover {
            color: orange;
        }

        &.disabeld {
            color: #c3c1c1;
        }
    }

    .calendar_header .left span:first-child,
    .calendar_header .right span:first-child {
        margin-right: 20px;
    }

    .calendar_header .center {
        flex: 1;
        text-align: center;
        // 不能被选中文字
        user-select: none;
    }

    .calendar_header .center select {
        border: 1px solid rgb(213, 213, 213);
        border-radius: 3px;
        font-size: 13px;
        // 不能被选中
        user-select: none;
    }

    .table_box {
        margin-top: 10px;
        width: 350px;
        padding: 4px;
        // border: 1px solid #e2e2e2;
    }

    table {
        // 不能被选中文字。这个属性是继承的。
        user-select: none;
        line-height: 20px;
    }

    table,
    tr,
    td,
    th {
        border-collapse: collapse;
        /* border: 1px solid rgb(166, 166, 166); */
        font-weight: normal;
    }

    td {
        width: 50px;
        height: 36px;
        color: #606266;
        text-align: center;
        font-size: 12px;
        cursor: pointer;

        // 淡色
        &.dan {
            color: #d1d1d1;
        }

        &:hover {
            background-color: rgb(233, 244, 177);
        }
    }

    th {
        color: rgb(77, 77, 77);
    }

    p {
        margin: 0;
        padding: 0;
    }
}
</style>